package com.lemon.security.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.lemon.core.utils.ConverterUtil;
import com.lemon.core.utils.DateUtil;
import com.lemon.security.properties.JwtConfigProperties;
import com.lemon.security.dto.LoginUserDetail;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 李猛
 * @datetime 2024/1/12 9:52
 * @description 类对象
 */
public class JwtUtil {
    /**
     * 令牌加密算法
     */
    public final static SecureDigestAlgorithm<SecretKey, SecretKey> SECURE_ALGORITHM = Jwts.SIG.HS256;

    /**
     * 从spring容器中获取配置信息
     */
    private static final JwtConfigProperties JWT_PROPERTIES = SpringUtil.getBean(JwtConfigProperties.class);
    /**
     * 密钥
     */
    public final static SecretKey SECRET_KEY = Keys.hmacShaKeyFor(JWT_PROPERTIES.getSecret().getBytes());

    /**
     * 获取HttpServletRequest
     *
     * @return
     */
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes.getRequest();
    }

    /**
     * 获取token
     *
     * @return
     */
    public static String getToken() {
        return getRequest().getHeader(JWT_PROPERTIES.getHeader());
    }

    /**
     * 创建 token
     *
     * @return
     */
    public static String createToken(LoginUserDetail user) {
        //1.登录的用户信息转map
        Map<String, Object> userMap = ConverterUtil.toMap(user);

        //2.过期时间
        Date now = new Date();//当前时间
        Date exprireDate = DateUtil.add(now, JWT_PROPERTIES.getExpireTime(), TimeUnit.SECONDS);

        //3.令牌ID
        String id = IdUtil.getSnowflakeNextIdStr();

        //4.创建JWT Token，并返回
        return Jwts.builder()
                .header()// 设置头部信息header
                .add("typ", "JWT")
                .add("alg", "HS256")
                .and()
                .claims(userMap)//设置自定义负载信息payload
                .id(id)//令牌ID
                .expiration(exprireDate)//过期日期，要大于签发时间
                .issuedAt(now)//签发时间
                //.subject(SUBJECT)//主题
                .issuer(user.getName())//签发者
                .signWith(SECRET_KEY, SECURE_ALGORITHM)//签名
                .compact();
    }

    /**
     * 解析token
     *
     * @param token
     * @return
     */
    public static Jws<Claims> parseToken(String token) {
        return Jwts.parser().verifyWith(SECRET_KEY).build().parseSignedClaims(token);
    }

    /**
     * 验证token是否正确
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        try {
            parseToken(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据token获取载荷信息
     *
     * @param token
     * @return
     */
    public static LoginUserDetail getCurrentUser(String token) {
        Claims payload = parseToken(token).getPayload();
        LoginUserDetail user = new LoginUserDetail();
        user.setUserId(payload.get("userId", Long.class));
        user.setTenantId(payload.get("tenantId", Long.class));
        user.setName(payload.get("name", String.class));
        user.setUsername(payload.get("username", String.class));
        return user;
    }

    /**
     * 获取登录用户信息
     *
     * @return
     */
    public static LoginUserDetail getCurrentUser() {
        return getCurrentUser(getToken());
    }
}
